package cn.itcast.bos.realm;

import java.util.List;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

import cn.itcast.bos.dao.system.PermissionRepository;
import cn.itcast.bos.domain.system.Permission;
import cn.itcast.bos.domain.system.Role;
import cn.itcast.bos.domain.system.User;
import cn.itcast.bos.service.system.PermissionService;
import cn.itcast.bos.service.system.RoleService;
import cn.itcast.bos.service.system.UserService;

/**
 * 用户登陆的realm
 * 
 * @author 艾欣
 *
 */
public class BosRealm extends AuthorizingRealm {
	// 注入业务层
	@Autowired
	private UserService us;
	// 注入角色的业务层
	@Autowired
	private RoleService rs;
	// 注入权限dao
	@Autowired
	private PermissionService ps;

	/**
	 * 用户的授权
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
		System.out.println("授权管理已经开启");
		SimpleAuthorizationInfo authorizationinfo = new SimpleAuthorizationInfo();
		// 根据当前用户查询权限
		Subject subject = SecurityUtils.getSubject();
		// 获取用户
		User user = (User) subject.getPrincipal();
		// 查询角色
		List<Role> roles = rs.findByUser(user);
		for (Role role : roles) {
			authorizationinfo.addRole(role.getKeyword());
		}

		// 调用业务层查询权限
		List<Permission> permissions = ps.findByUser(user);
		for (Permission permission : permissions) {
			authorizationinfo.addStringPermission(permission.getKeyword());
		}
		return authorizationinfo;
	}

	/**
	 * 用户的认证
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {
		System.out.println("认证管理已经开启");
		// 转换token为用户对象User
		UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
		// 调用业务层查询用户名是否存在然后进行判断
		User user = us.findByUsername(usernamePasswordToken.getUsername());
		// 判断
		if (user == null) {
			// 用户名不存在
			// 参数一： 期望登录后，保存在Subject中信息
			// 参数二： 如果返回为null 说明用户不存在，报用户名
			// 参数三 ：realm名称
			return null;
		} else {
			// 用户名存在
			// 当返回用户密码时，securityManager安全管理器，自动比较返回密码和用户输入密码是否一致
			// 如果密码一致 登录成功， 如果密码不一致 报密码错误异常
			return new SimpleAuthenticationInfo(user, user.getPassword(),
					getName());
		}
	}
}
